Source code for nlp_architect.utils.ansi2html

#!/usr/bin/env python

# This file was taken from:
# https://github.com/Kronuz/ansi2html/blob/master/ansi2html.py
# Copyright © 2013 German M. Bravo (Kronuz)
# License: https://github.com/Kronuz/ansi2html/blob/master/LICENSE
# Changes made to original file: removed main, added run() function.
from __future__ import print_function

import re
import sys

_ANSI2HTML_STYLES = {}
# pylint: disable=anomalous-backslash-in-string
ANSI2HTML_CODES_RE = re.compile('(?:\033\\[(\\d+(?:;\\d+)*)?([cnRhlABCDfsurgKJipm]))')
ANSI2HTML_PALETTE = {
    # See http://ethanschoonover.com/solarized
    'solarized': ['#073642', '#D30102', '#859900', '#B58900', '#268BD2', '#D33682', '#2AA198',
                  '#EEE8D5', '#002B36', '#CB4B16', '#586E75', '#657B83', '#839496', '#6C71C4',
                  '#93A1A1', '#FDF6E3'],
    # Above mapped onto the xterm 256 color palette
    'solarized-xterm': ['#262626', '#AF0000', '#5F8700', '#AF8700', '#0087FF', '#AF005F',
                        '#00AFAF', '#E4E4E4', '#1C1C1C', '#D75F00', '#585858', '#626262',
                        '#808080', '#5F5FAF', '#8A8A8A', '#FFFFD7'],
    # Gnome default:
    'tango': ['#000000', '#CC0000', '#4E9A06', '#C4A000', '#3465A4', '#75507B', '#06989A',
              '#D3D7CF', '#555753', '#EF2929', '#8AE234', '#FCE94F', '#729FCF', '#AD7FA8',
              '#34E2E2', '#EEEEEC'],
    # xterm:
    'xterm': ['#000000', '#CD0000', '#00CD00', '#CDCD00', '#0000EE', '#CD00CD', '#00CDCD',
              '#E5E5E5', '#7F7F7F', '#FF0000', '#00FF00', '#FFFF00', '#5C5CFF', '#FF00FF',
              '#00FFFF', '#FFFFFF'],
    'console': ['#000000', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA', '#00AAAA',
                '#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55', '#5555FF', '#FF55FF',
                '#55FFFF', '#FFFFFF'],
}


def _ansi2html_get_styles(palette):
    if palette not in _ANSI2HTML_STYLES:
        p = ANSI2HTML_PALETTE.get(palette, ANSI2HTML_PALETTE['console'])

        regular_style = {
            '1': '',  # bold
            '2': 'opacity:0.5',
            '4': 'text-decoration:underline',
            '5': 'font-weight:bold',
            '7': '',
            '8': 'display:none',
        }
        bold_style = regular_style.copy()
        for i in range(8):
            regular_style['3%s' % i] = 'color:%s' % p[i]
            regular_style['4%s' % i] = 'background-color:%s' % p[i]

            bold_style['3%s' % i] = 'color:%s' % p[i + 8]
            bold_style['4%s' % i] = 'background-color:%s' % p[i + 8]

        # The default xterm 256 colour p:
        indexed_style = {}
        for i in range(16):
            indexed_style['%s' % i] = p[i]

        for rr in range(6):
            for gg in range(6):
                for bb in range(6):
                    i = 16 + rr * 36 + gg * 6 + bb
                    r = (rr * 40 + 55) if rr else 0
                    g = (gg * 40 + 55) if gg else 0
                    b = (bb * 40 + 55) if bb else 0
                    indexed_style['%s' % i] = ''.join(
                        '%02X' % c if 0 <= c <= 255 else None for c in (r, g, b))

        for g in range(24):
            i = g + 232
            j = g * 10 + 8
            indexed_style['%s' % i] = ''.join(
                '%02X' % c if 0 <= c <= 255 else None for c in (j, j, j))

        _ANSI2HTML_STYLES[palette] = (regular_style, bold_style, indexed_style)
    return _ANSI2HTML_STYLES[palette]


[docs]def ansi2html(text, palette='solarized'): # pylint: disable=too-many-branches, too-many-statements def _ansi2html(m): if m.group(2) != 'm': return '' state = None sub = '' cs = m.group(1) cs = cs.strip() if cs else '' for c in cs.split(';'): c = c.strip().lstrip('0') or '0' if c == '0': while stack: sub += '</span>' stack.pop() elif c in ('38', '48'): extra = [c] state = 'extra' elif state == 'extra': if c == '5': state = 'idx' elif c == '2': state = 'r' elif state: if state == 'idx': extra.append(c) state = None color = indexed_style.get(c) # 256 colors if color is not None: sub += \ '<span style="%s:%s">' % \ ('color' if extra[0] == '38' else 'background-color', color) stack.append(extra) elif state in ('r', 'g', 'b'): extra.append(c) if state == 'r': state = 'g' elif state == 'g': state = 'b' else: state = None try: color = '#' + ''.join( '%02X' % c if 0 <= c <= 255 else None for x in extra for c in [int(x)]) except (ValueError, TypeError): pass else: sub += \ '<span style="%s:%s">' % \ ('color' if extra[0] == '38' else 'background-color', color) stack.append(extra) else: if '1' in stack: style = bold_style.get(c) else: style = regular_style.get(c) if style is not None: sub += '<span style="%s">' % style stack.append(c) # Still needs to be added to the stack even if style is empty # (so it can check '1' in stack above, for example) return sub stack = [] regular_style, bold_style, indexed_style = _ansi2html_get_styles(palette) sub = ANSI2HTML_CODES_RE.sub(_ansi2html, text) while stack: sub += '</span>' stack.pop() return sub
[docs]def run(file, out): try: html = '' try: with open(file) as fp: html += '<pre>' + ansi2html(fp.read()) + '</pre>' except IOError: print("File not found: %r" % 'pylint.txt', file=sys.stderr) with open(out, 'w') as out_fp: out_fp.write(html) except KeyboardInterrupt: pass